package xin.marcher.module.diplomacy.test.mapper;

import junit.framework.TestCase;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import xin.marcher.module.common.domain.BaseDO;
import xin.marcher.module.diplomacy.DiplomacyApplication;
import xin.marcher.module.diplomacy.domain.entity.*;
import xin.marcher.module.diplomacy.mapper.*;

import javax.annotation.Resource;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.net.URL;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 *
 */
@SpringBootTest(classes = DiplomacyApplication.class)
@RunWith(SpringJUnit4ClassRunner.class)
public class ForJmeterCreateMockData extends TestCase {

    public static final Range FRONT_CATEGORY_ID_RANGE = new Range(1, 100L);

    public static final Range SKU_INFO_SKU_ID_RANGE = new Range(8_000_000_001L, 8_000_010_000L);

    public static final Range ITEM_INFO_ITEM_ID_RANGE = new Range(100_000_000_001L, 100_000_001_000L);

    public static final Range PRODUCING_AREA_ID_RANGE = new Range(1, 100L);

    public static final Range BRAND_INFO_ID_RANGE = new Range(1, 100L);

    public static final Range CATEGORY_INFO_ID_RANGE = new Range(1, 100L);

    public static final Range QUALITY_CONTROLL_ID_RANGE = new Range(1, 10_000L);

    public static final Range ITEM_VIDEO_IMG_ID_RANGE = new Range(1, 2_000L);

    public static final Range BUYER_INFO_ID_RANGE = new Range(1, 500L);

    public static final Range LABEL_ID_RANGE = new Range(1, 20_000L);

    public static final AtomicInteger ATOMIC_INTEGER = new AtomicInteger();

    @Resource
    private FrontCategoryMapper frontCategoryMapper;

    @Resource
    private FrontCategoryRelationMapper frontCategoryRelationMapper;

    @Resource
    private SkuInfoMapper skuInfoMapper;

    @Resource
    private ItemInfoMapper itemInfoMapper;

    @Resource
    private AttributeExtendMapper attributeExtendMapper;

    @Resource
    private ProducingAreaMapper producingAreaMapper;

    @Resource
    private BrandInfoMapper brandInfoMapper;

    @Resource
    private CategoryBaseMapper categoryMapper;

    @Resource
    private QualityControlMapper qualityControlMapper;

    @Resource
    private ItemVideoImgMapper itemVideoImgMapper;

    @Resource
    private BuyerInfoMapper buyerInfoMapper;

    @Resource
    private FrontCategoryLabelGroupRelationMapper frontCategoryLabelGroupRelationMapper;

    @Resource
    private LabelMapper labelMapper;

    @Resource
    private ProductLabelRelationMapper productLabelRelationMapper;

    @Resource
    private RestHighLevelClient restHighLevelClient;

    /**
     * front_category 表
     */
    @Test
    public void frontCategory() {
        List<Runnable> tasks = new ArrayList<>();
        for (Long id : FRONT_CATEGORY_ID_RANGE.asList()) {
            FrontCategoryDO entity = new FrontCategoryDO();
            entity.setCategoryName(appendGrowingNum("CategoryName"));
            entity.setCategorySort(getFixedInteger());
            entity.setIcon(concatUrl("icon"));
            entity.setShowMark(getYesInteger());
            entity.setLastFlag(getNoInteger());
            entity.setChannel(computeChannelById(id));
            entity.setSellerType(computeSellerTypeById(id));
            entity.setFeature(getNull());
            setCommonFieldValue(entity);
            tasks.add(() -> frontCategoryMapper.insert(entity));
        }
        executeTaskWithThreadPool(tasks);
    }

    /**
     * front_category_relation 表
     */
    @Test
    public void frontCategoryRelation() {
        List<Runnable> tasks = new ArrayList<>();
        for (Long skuId : SKU_INFO_SKU_ID_RANGE.asList()) {
            FrontCategoryRelationDO entity = new FrontCategoryRelationDO();
            entity.setFrontCategoryId(FRONT_CATEGORY_ID_RANGE.randomOne());
            entity.setParticipateType(getParticipateTypeSku());
            entity.setParticipateId(skuId.toString());
            entity.setRelationSort(getFixedInteger());
            setCommonFieldValue(entity);
            tasks.add(() -> frontCategoryRelationMapper.insert(entity));
        }
        executeTaskWithThreadPool(tasks);
    }

    /**
     * item_info 表
     */
    @Test
    public void itemInfo() {
        List<Runnable> tasks = new ArrayList<>();
        for (Long itemId : ITEM_INFO_ITEM_ID_RANGE.asList()) {
            ItemInfoDO entity = new ItemInfoDO();
            entity.setItemId(itemId.toString());
            entity.setItemName(appendGrowingNum("itemName"));
            entity.setRecommend(appendGrowingNum("Recommend"));
            entity.setItemType(computeSellerTypeById(itemId));
            entity.setChannel(computeChannelById(itemId));
            entity.setSellerType(entity.getItemType());
            entity.setProducingAreaId(PRODUCING_AREA_ID_RANGE.randomOne().intValue());
            entity.getItemStatus();
            entity.setBrandId(BRAND_INFO_ID_RANGE.randomOne().intValue());
            entity.setShelfLife(getFixedShelfLife());
            //entity.setStoreConditionType();
            entity.setCategoryId(CATEGORY_INFO_ID_RANGE.randomOne().intValue());
            entity.setFirstCategoryId(entity.getCategoryId());
            entity.setSecondCategoryId(entity.getCategoryId());
            entity.setThirdCategoryId(entity.getCategoryId());
            setCommonFieldValue(entity);
            tasks.add(() -> itemInfoMapper.insert(entity));
        }
        executeTaskWithThreadPool(tasks);
    }

    /**
     * sku_info 表
     */
    @Test
    public void skuInfo() {
        List<Runnable> tasks = new ArrayList<>();
        for (Long skuId : SKU_INFO_SKU_ID_RANGE.asList()) {
            SkuInfoDO entity = new SkuInfoDO();
            Long itemId = ITEM_INFO_ITEM_ID_RANGE.randomOne();
            entity.setSkuId(skuId.toString());
            entity.setItemId(itemId.toString());
            entity.setSkuName(appendGrowingNum("SkuName"));
            entity.setSkuType(computeSellerTypeById(itemId));
            entity.setBasePrice(getRandomPrice());
            entity.setVipPrice(entity.getBasePrice() - 10);
            entity.setSellerType(entity.getSkuType());
            setCommonFieldValue(entity);
            tasks.add(() -> skuInfoMapper.insert(entity));
        }
        executeTaskWithThreadPool(tasks);
    }

    /**
     * attribute_extend 表
     */
    @Test
    public void attributeExtend() {
        List<Runnable> tasks = new ArrayList<>();
        for (Long skuId : SKU_INFO_SKU_ID_RANGE.asList()) {
            AttributeExtendDO entity = new AttributeExtendDO();
            entity.setParticipateId(skuId.toString());
            entity.setParticipateType(2);
            entity.setAttributeContent("{}");
            entity.setVersionId(getFixedInteger());
            setCommonFieldValue(entity);
            tasks.add(() -> attributeExtendMapper.insert(entity));
        }
        for (Long itemId : ITEM_INFO_ITEM_ID_RANGE.asList()) {
            AttributeExtendDO entity = new AttributeExtendDO();
            entity.setParticipateId(itemId.toString());
            entity.setParticipateType(1);
            entity.setAttributeContent("{}");
            setCommonFieldValue(entity);
            tasks.add(() -> attributeExtendMapper.insert(entity));
        }
        executeTaskWithThreadPool(tasks);
    }

    /**
     * quality_control 表
     */
    @Test
    public void qualityControl() {
        List<Runnable> tasks = new ArrayList<>();
        for (Long skuId : SKU_INFO_SKU_ID_RANGE.asList()) {
            QualityControlDO entity = new QualityControlDO();
            entity.setSkuId(skuId.toString());
            entity.setQcName(appendGrowingNum("质检报告"));
            entity.setQcImgUrl(concatUrl("qcImageUrl"));
            entity.setQcSort(getFixedInteger());
            setCommonFieldValue(entity);
            tasks.add(() -> qualityControlMapper.insert(entity));
        }
        executeTaskWithThreadPool(tasks);
    }

    /**
     * item_video_img 表
     */
    @Test
    public void itemVideoImg() {
        List<Runnable> tasks = new ArrayList<>();
        // 主图
        for (Long itemId : ITEM_INFO_ITEM_ID_RANGE.asList()) {
            ItemVideoImgDO entity = new ItemVideoImgDO();
            entity.setItemId(itemId.toString());
            entity.setContentType(1);
            entity.setContentUrl(concatUrl("ContentUrl"));
            entity.setContentSort(getFixedInteger());
            entity.setChannel(computeChannelById(itemId));
            setCommonFieldValue(entity);
            tasks.add(() -> itemVideoImgMapper.insert(entity));
        }
        // 轮播图
        for (Long itemId : ITEM_INFO_ITEM_ID_RANGE.asList()) {
            ItemVideoImgDO entity = new ItemVideoImgDO();
            entity.setItemId(itemId.toString());
            entity.setContentType(2);
            entity.setContentUrl(concatUrl("ContentUrl"));
            entity.setContentSort(getFixedInteger());
            entity.setChannel(computeChannelById(itemId));
            setCommonFieldValue(entity);
            tasks.add(() -> itemVideoImgMapper.insert(entity));
        }
        executeTaskWithThreadPool(tasks);
    }

    /**
     * buyer_info 表
     */
    @Test
    public void buyerInfo() {
        List<Runnable> tasks = new ArrayList<>();
        for (Long categoryId : CATEGORY_INFO_ID_RANGE.asList()) {
            BuyerInfoDO entity = new BuyerInfoDO();
            entity.setRealName(appendGrowingNum("RealName"));
            entity.setRoster(appendGrowingNum("Roster"));
            entity.setImageUrl(concatUrl("imageUrl"));
            entity.setDescription(appendGrowingNum("Decription"));
            entity.setCategoryId(categoryId.toString());
            setCommonFieldValue(entity);
            tasks.add(() -> buyerInfoMapper.insert(entity));
        }
        executeTaskWithThreadPool(tasks);
    }

    /**
     * lam_front_category_label_relation 表
     */
    @Test
    public void frontCategoryLabelRelation() {
        List<Runnable> tasks = new ArrayList<>();
        // frontCategory -> label
        // label -> frontCategory
        // 保证覆盖到每个分类和标签
        for (Long frontCategoryId : FRONT_CATEGORY_ID_RANGE.asList()) {
            FrontCategoryLabelRelationDO entity = new FrontCategoryLabelRelationDO();
            entity.setFrontCategoryId(frontCategoryId);
            entity.setLabelId(LABEL_ID_RANGE.randomOne());
            setCommonFieldValue(entity);
            tasks.add(() -> frontCategoryLabelGroupRelationMapper.insert(entity));
        }
        for (Long labelId : LABEL_ID_RANGE.asList()) {
            FrontCategoryLabelRelationDO entity = new FrontCategoryLabelRelationDO();
            entity.setFrontCategoryId(FRONT_CATEGORY_ID_RANGE.randomOne());
            entity.setLabelId(labelId);
            setCommonFieldValue(entity);
            tasks.add(() -> frontCategoryLabelGroupRelationMapper.insert(entity));
        }
        executeTaskWithThreadPool(tasks);
    }

    /**
     * lam_label 表
     */
    @Test
    public void label() {
        List<Runnable> tasks = new ArrayList<>();
        for (Long labelId : LABEL_ID_RANGE.asList()) {
            LabelDO entity = new LabelDO();
            entity.setLabelName(appendGrowingNum("LabelName"));
            entity.setLabelComment(appendGrowingNum("labelComment"));
            setCommonFieldValue(entity);
            tasks.add(() -> labelMapper.insert(entity));
        }
        executeTaskWithThreadPool(tasks);
    }

    /**
     * product_label_relation
     */
    @Test
    public void productLabelRelation() {
        List<Runnable> tasks = new ArrayList<>();
        // 每个label都关联好skuId
        for (Long labelId : LABEL_ID_RANGE.asList()) {
            ProductLabelRelationDO entity = new ProductLabelRelationDO();
            entity.setLabelId(labelId);
            Long skuId = SKU_INFO_SKU_ID_RANGE.randomOne();
            entity.setParticipantId(skuId.toString());
            entity.setParticipantType(2);
            setCommonFieldValue(entity);
            tasks.add(() -> productLabelRelationMapper.insert(entity));
        }
        executeTaskWithThreadPool(tasks);
    }

    /**
     * 商品索引数据
     */
    @Test
    public void productIndex() throws IOException, ParseException {
        // 读取测试的skuName
        URL url = ClassLoader.getSystemResource("skuNames.txt");
        File file = new File(url.getFile());
        FileReader fileReader = new FileReader(file);
        BufferedReader bufferedReader = new BufferedReader(fileReader);
        String line;
        List<String> skuNames = new ArrayList<>();
        while ((line = bufferedReader.readLine()) != null) {
            skuNames.add(line);
        }

        // 查询sku_info表，每次查询1000个
        List<Long> skuIds = SKU_INFO_SKU_ID_RANGE.asList();
        List<Long> subList;
        int from = 0;
        int i = 0;
        while (CollectionUtils.isNotEmpty(subList = skuIds.subList(from, from + 1000))) {
            List<String> collect = subList.stream().map(Object::toString).collect(Collectors.toList());
            List<ProductSearchDO> productSearchDOS = skuInfoMapper.queryProductSearchInfo(collect);
            BulkRequest bulkRequest = new BulkRequest();
            for (ProductSearchDO productSearchDO : productSearchDOS) {
                Map<String, Object> jsonMap = new HashMap<>();
                jsonMap.put("skuName", skuNames.get(i));
                jsonMap.put("basePrice", productSearchDO.getBasePrice());
                jsonMap.put("vipPrice", productSearchDO.getVipPrice());
                jsonMap.put("createTime", DateUtils.parseDate("2022-04-02 00:00:00", "yyyy-MM-dd HH:mm:ss"));
                jsonMap.put("updateTime", DateUtils.parseDate("2022-04-02 00:00:00", "yyyy-MM-dd HH:mm:ss"));
                IndexRequest indexRequest = new IndexRequest("sku_info_index").id(productSearchDO.getSkuId()).source(jsonMap);
                bulkRequest.add(indexRequest);
                i++;
            }

            restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
            from = from + 1000;
            if (from > skuIds.size()) {
                break;
            }
        }
    }


    private Integer getRandomPrice() {
        return RandomUtils.nextInt(100, 10001);
    }

    private Integer getFixedShelfLife() {
        return 1000;
    }


    private void executeTaskWithThreadPool(List<Runnable> tasks) {
        ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) Executors.newFixedThreadPool(100);
        for (Runnable task : tasks) {
            threadPoolExecutor.execute(task);
        }
        // 循环等待线程池里的任务都执行完
        while (threadPoolExecutor.getQueue().size() != 0) {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        // 现在可以关闭线程池了
        threadPoolExecutor.shutdown();
    }

    private Integer getParticipateTypeSku() {
        return 2;
    }

    private void setCommonFieldValue(BaseDO entity) {
        try {
            entity.setDelFlag(getYesInteger());
            entity.setCreateUser(getFixedInteger());
            entity.setCreateTime(DateUtils.parseDate("2022-04-02 00:00:00", "yyyy-MM-dd HH:mm:ss"));
            entity.setUpdateUser(getFixedInteger());
            entity.setUpdateTime(DateUtils.parseDate("2022-04-02 00:00:00", "yyyy-MM-dd HH:mm:ss"));
        } catch (ParseException ignore) {
        }
    }

    private String getNull() {
        return null;
    }

    private Integer computeSellerTypeById(Long id) {
        return (int) (id % 2) + 1;
    }

    private Integer computeChannelById(Long id) {
        return (int) (id % 5) + 1;
    }

    private Integer getNoInteger() {
        return 0;
    }

    private Integer getYesInteger() {
        return 1;
    }

    private String concatUrl(String str) {
        return "http://" + str + ATOMIC_INTEGER.incrementAndGet();
    }

    private String appendGrowingNum(String str) {
        return str + ATOMIC_INTEGER.incrementAndGet();
    }

    private Integer getFixedInteger() {
        return 1;
    }

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public static class Range {
        // 前闭
        private long start;
        // 后也闭
        private long end;

        public List<Long> asList() {
            List<Long> list = new ArrayList<>();
            for (long i = start; i <= end; i++) {
                list.add(i);
            }
            return list;
        }


        public Long randomOne() {
            return RandomUtils.nextLong(start, end + 1);
        }
    }


}
